package com.sourcespro;

import org.apache.commons.lang3.StringUtils;
import org.jdom.Content;
import org.jdom.Document;
import org.jdom.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * genCode
 *
 * @author zhanghaowei
 * @date 2018/6/13
 */
public class MapperUpdate {

    private static final Logger logger = LoggerFactory.getLogger(MapperUpdate.class);

    private final static String SPACE = "  ";
    private final static String NEW_LINE = "\n";
    private final static String SPACE_NEW_LINE = "\n  ";
    private final static String TAB_NEW_LINE = "\n\t";

    public static Document update(Document document, String tableName, Boolean isType){
        Element rootElement = document.getRootElement();
        Element resultMap = rootElement.getChild("resultMap");
        List<Element> children = resultMap.getChildren();
        List<String> columns = new ArrayList<>();
        int pos = 0;
        int line = 1;
        for (Element child : children) {
            String column = child.getAttribute("column").getValue();
            pos += column.length();
            if (pos >= 80 * line){
                columns.add("\n\t" + column);
                line ++;
            } else {
                columns.add(column);
            }
            logger.info(column);
        }
        String baseColumn = "\n\t" + StringUtils.join(columns, ",") + "\n  ";
        logger.info("baseColumn: {}", baseColumn);
        //创建baseColumn
        rootElement.addContent(SPACE);
        Element baseColumnEle = new Element("sql");
        baseColumnEle.setAttribute("id", "baseColumn");
        baseColumnEle.addContent(baseColumn);
        rootElement.addContent(baseColumnEle);

        //delete by id & uuid
        //1、删除原delete
        rootElement.removeChild("delete");
        //2、添加伪delete by id
        rootElement.addContent(SPACE_NEW_LINE);
        Element updateDelEle = new Element("update");
        updateDelEle.setAttribute("id","deleteByPrimaryKey");
        updateDelEle.setAttribute("parameterType","java.lang.Integer");
        updateDelEle.addContent("\n    update "+ tableName +"\n" +
                "    set status = 0\n" +
                "    where id = #{id,jdbcType=INTEGER}\n" + SPACE);
        rootElement.addContent(updateDelEle);
        //3、添加伪delete by uuid
        rootElement.addContent(SPACE_NEW_LINE);
        Element updateDelEle2 = new Element("update");
        updateDelEle2.setAttribute("id","deleteByUuid");
        updateDelEle2.setAttribute("parameterType","java.lang.String");
        updateDelEle2.addContent("\n    update "+ tableName +"\n" +
                "    set status = 0\n" +
                "    where id = #{uuid,jdbcType=VARCHAR}\n" + SPACE);
        rootElement.addContent(updateDelEle2);
        //4、添加伪batch delete by uuid
        rootElement.addContent(SPACE_NEW_LINE);
        Element updateDelEle3 = new Element("update");
        updateDelEle3.setAttribute("id","batchDelete");
        updateDelEle3.setAttribute("parameterType","java.util.List");
        updateDelEle3.addContent("\n    update "+ tableName +"\n" +
                "    set status = 0\n" +
                "    where uuid in\n" +
                "    <foreach collection=\"list\" item=\"uuid\" open=\"(\" separator=\",\" close=\")\">\n" +
                "      #{uuid}\n" +
                "    </foreach>\n" + SPACE);
        rootElement.addContent(updateDelEle3);

        //批量insert
        rootElement.addContent(SPACE_NEW_LINE);
        Element originInsert = rootElement.getChild("insert");
        String originInsertTextNormalize = originInsert.getText();
        originInsertTextNormalize = StringUtils.stripStart(originInsertTextNormalize, null);
        //values后面加foreach
        int index = originInsertTextNormalize.indexOf("values");
        StringBuilder sb = new StringBuilder(originInsertTextNormalize);
        sb.insert(0, TAB_NEW_LINE);
        sb.insert(index + 8, "\n\t<foreach item=\"item\" collection=\"list\" separator=\",\"> " + TAB_NEW_LINE);
        sb.append("\t</foreach>\n");
        String batchInsertContent = sb.toString().replaceAll("#\\{", "#{item.");
        Element batchInsertContentEle = new Element("insert");
        batchInsertContentEle.setAttribute("id","batchInsert");
        batchInsertContentEle.setAttribute("parameterType","java.util.List");
        batchInsertContentEle.setAttribute("keyProperty","id");
        batchInsertContentEle.setAttribute("useGeneratedKeys","true");
        batchInsertContentEle.addContent(batchInsertContent + SPACE);
        rootElement.addContent(batchInsertContentEle);

        //select
        List<Element> rootElementChildren = rootElement.getChildren();
        for (Element child : rootElementChildren) {
            switch (child.getAttribute("id").getValue()){
                case "selectByPrimaryKey":
                    child.setText("\n\tselect <include refid=\"baseColumn\"/>\n" +
                            "    from " + tableName + "\n" +
                            "    where id = #{id,jdbcType=INTEGER}\n  ");
                    break;
                case "selectAll":
                    child.setText("\n\tselect <include refid=\"baseColumn\"/>\n" +
                            "    from " + tableName + "\n" +
                            "    where status != 0\n" +
                            "    <include refid=\"whereMapSql\"/>\n" +
                            "    <include refid=\"orderLimitSql\"/>\n  ");
                    break;
                case "selectCount":
                    child.setText("\n   select count(id)\n" +
                            "    from " + tableName + "\n" +
                            "    where status != 0\n" +
                            "    <include refid=\"whereMapSql\"/>\n");
                    break;
                default:
                    logger.info("other element");
            }
        }

        //selelct count
        rootElement.addContent(SPACE_NEW_LINE);
        Element findCountEle = new Element("select");
        findCountEle.setAttribute("id","selectCount");
        findCountEle.setAttribute("resultMap","BaseResultMap");
        findCountEle.addContent("\n    select count(id)\n" +
                "    from " + tableName + "\n" +
                "    <include refid=\"whereMapSql\"/>" + SPACE_NEW_LINE);
        rootElement.addContent(findCountEle);

        //find by uuid
        rootElement.addContent(SPACE_NEW_LINE);
        Element findByUuidEle = new Element("select");
        findByUuidEle.setAttribute("id","findByUuid");
        findByUuidEle.setAttribute("parameterType","java.lang.String");
        findByUuidEle.setAttribute("resultMap","BaseResultMap");
        findByUuidEle.addContent("\n    select <include refid=\"baseColumn\"/>\n" +
                "    from " + tableName + "\n" +
                "    where uuid = #{uuid} " + SPACE_NEW_LINE);
        rootElement.addContent(findByUuidEle);

        //batch query by ids
        rootElement.addContent(SPACE_NEW_LINE);
        Element batchQueryByIdEle = new Element("select");
        batchQueryByIdEle.setAttribute("id","batchQueryByIds");
        batchQueryByIdEle.setAttribute("parameterType","java.util.List");
        batchQueryByIdEle.setAttribute("resultMap","BaseResultMap");
        batchQueryByIdEle.addContent("\n    select <include refid=\"baseColumn\"/>\n" +
                "    from " + tableName + "\n" +
                "    where id in\n" +
                "    <foreach collection=\"list\" item=\"id\" open=\"(\" separator=\",\" close=\")\">\n" +
                "      #{id}\n" +
                "    </foreach>\n" +
                "    and status != 0" + SPACE_NEW_LINE);
        rootElement.addContent(batchQueryByIdEle);

        //batch query by uuids
        rootElement.addContent(SPACE_NEW_LINE);
        Element batchQueryByUuidEle = new Element("select");
        batchQueryByUuidEle.setAttribute("id","batchQueryByUuids");
        batchQueryByUuidEle.setAttribute("parameterType","java.util.List");
        batchQueryByUuidEle.setAttribute("resultMap","BaseResultMap");
        batchQueryByUuidEle.addContent("\n    select <include refid=\"baseColumn\"/>\n" +
                "    from " + tableName + "\n" +
                "    where id in\n" +
                "    <foreach collection=\"list\" item=\"uuid\" open=\"(\" separator=\",\" close=\")\">\n" +
                "      '${uuid}'\n" +
                "    </foreach>\n" +
                "    and status != 0" + SPACE_NEW_LINE);
        rootElement.addContent(batchQueryByUuidEle);

        if (isType) {
            //findByProjectIdAndLevel
            rootElement.addContent(SPACE_NEW_LINE);
            Element findByProjectIdAndLevelEle = new Element("select");
            findByProjectIdAndLevelEle.setAttribute("id","findByProjectIdAndLevel");
            findByProjectIdAndLevelEle.setAttribute("resultMap","BaseResultMap");
            findByProjectIdAndLevelEle.addContent("\n    select <include refid=\"baseColumn\"/>\n" +
                    "    from " + tableName + "\n" +
                    "    where project_id = #{projectId}\n" +
                    "    and level = #{level}\n" +
                    "    and status != 0 " + SPACE_NEW_LINE);
            rootElement.addContent(findByProjectIdAndLevelEle);

            //findByOrgIdAndLevel
            rootElement.addContent(SPACE_NEW_LINE);
            Element findByOrgIdAndLevelEle = new Element("select");
            findByOrgIdAndLevelEle.setAttribute("id","findByOrgIdAndLevel");
            findByOrgIdAndLevelEle.setAttribute("resultMap","BaseResultMap");
            findByOrgIdAndLevelEle.addContent("\n    select <include refid=\"baseColumn\"/>\n" +
                    "    from " + tableName + "\n" +
                    "    where org_id = #{orgId}\n" +
                    "    and level = #{level}\n" +
                    "    and project_id is null\n" +
                    "    and status != 0 " + SPACE_NEW_LINE);
            rootElement.addContent(findByOrgIdAndLevelEle);

            //findByParentId
            rootElement.addContent(SPACE_NEW_LINE);
            Element findByParentIdEle = new Element("select");
            findByParentIdEle.setAttribute("id","findByParentId");
            findByParentIdEle.setAttribute("resultMap","BaseResultMap");
            findByParentIdEle.addContent("\n    select <include refid=\"baseColumn\"/>\n" +
                    "    from " + tableName + "\n" +
                    "    where parent_id = #{parentId}\n" +
                    "    and status != 0 " + SPACE_NEW_LINE);
            rootElement.addContent(findByParentIdEle);

        }

        //添加whereMap
        rootElement.addContent(SPACE_NEW_LINE);
        Element whereMapEle = new Element("sql");
        whereMapEle.setAttribute("id", "whereMapSql");
        whereMapEle.addContent("\n    <if test=\"whereMap != null\">\n" +
                "      <if test=\"whereMap.name != null and whereMap.name != ''\">\n" +
                "        and name like CONCAT('%',#{whereMap.name},'%')\n" +
                "      </if>\n" +
                "    </if>" + SPACE_NEW_LINE);
        rootElement.addContent(whereMapEle);

        //添加whereMap
        rootElement.addContent(SPACE_NEW_LINE);
        Element orderLimitEle = new Element("sql");
        orderLimitEle.setAttribute("id", "orderLimitSql");
        orderLimitEle.addContent("\n    <if test=\"orderColumn != null and orderSort != null\">\n" +
                "      order by ${orderColumn} ${orderSort}\n" +
                "    </if>\n" +
                "    <if test=\"orderColumn == null or orderSort == null\">\n" +
                "      order by id asc\n" +
                "    </if>\n" +
                "    <if test=\"startRecord != null and pageSize != null\">\n" +
                "      limit #{startRecord,jdbcType=INTEGER},#{pageSize,jdbcType=INTEGER}\n" +
                "    </if>" + SPACE_NEW_LINE);
        rootElement.addContent(orderLimitEle);
        rootElement.addContent(NEW_LINE);
        return document;
    }

}
